package com.adcc.soundalarm.fx.main;

import com.adcc.soundalarm.common.Constant;
import com.adcc.soundalarm.common.Log;
import com.adcc.soundalarm.config.regular.RegularXMLConfiguration;
import com.adcc.soundalarm.config.system.AlarmFactory;
import com.adcc.soundalarm.config.system.AppConfiguration;
import com.adcc.soundalarm.entity.LogEntity;
import com.adcc.soundalarm.entity.LogInfo;
import com.adcc.soundalarm.fx.alarm.AlarmView;
import com.adcc.soundalarm.fx.app.SysAlarmView;
import com.adcc.soundalarm.listener.RequestMessageListener;
import com.adcc.soundalarm.manager.RegularConfigManager;
import com.adcc.soundalarm.manager.SystemInfoManager;
import com.adcc.soundalarm.service.RequestService;
import com.adcc.soundalarm.sound.SoundAlarm;
import com.adcc.utility.time.Time;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;

import java.net.InetAddress;
import java.net.URL;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by ZHANG on 2017/3/23.
 */
public class MainViewController implements RequestMessageListener {

    // 远程请求类
    private RequestService requestService = RequestService.getInstance();

    // 声音告警类
    private SoundAlarm soundAlarm = SoundAlarm.getInstance();

    // 配置管理类
    private RegularXMLConfiguration regularXMLConfiguration = RegularXMLConfiguration.getInstance();

    // 临时配置管理类
    private RegularConfigManager regularConfigManager = RegularConfigManager.getInstance();

    //引入配置
    private AlarmFactory alarmFactory = AppConfiguration.getInstance().getAlarmFactory();

    // 提示信息框
    private AlarmView alarmView = new AlarmView();

    // 系统配置框
    private SysAlarmView sysAlarmView = new SysAlarmView();

    private Thread thread = null;

    //告警启动标志
    private boolean sysnStartFlag = true;


    private Alert checkError_alert = null;

    private Alert syncError_alert = null;

    // 定时检测GMS地址是否有效
    private ScheduledExecutorService checkIpService;

    //当前舞台
    private Stage stage;

    @FXML
    private ListView listLog;

    @FXML
    private TextField textLog;

    @FXML
    private CheckBox chkAMQS;

    @FXML
    private CheckBox chkMQ;

    @FXML
    private CheckBox chkGW;

    @FXML
    private CheckBox chkAuto;

    @FXML
    private ListView listState;

    @FXML
    private ListView listSaveState;


    @FXML
    private TableView tableLog;

    @FXML
    private TableColumn cellName;

    @FXML
    private TableColumn cellLevel;

    @FXML
    private TableColumn cellLog;

    @FXML
    private TableColumn cellTime;

    @FXML
    private TextField textSearch;


    public void buildEnvironment(Stage stage) {
        this.stage = stage;
    }

    @Override
    public void onMessage(Object message) {
        final LogInfo info = (LogInfo) message;
        checkIfAlarmAndShowErrorMsgForSysState(info);
    }

    /**
     * 告警信息追加
     *
     * @param logEntity
     */
    private void appendMsgAndShowAlarmDialog(final LogEntity logEntity) {
        if (!soundAlarm.isMuteFlag()) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    showAlarmDialog();
                    alarmView.getAlarmDialogController().appendMessageToTextArea(logEntity);
                }
            });
        }
    }

    /**
     * 是否包含
     *
     * @param list
     * @param value
     * @return
     */
    private boolean ifContain(List<String> list, String value) {
        boolean flag = false;
        if (list != null && list.size() > 0) {
            for (String info : list) {
                if (value.contains(info)) {
                    flag = true;
                    return flag;
                }
            }
        }
        return flag;
    }

    /**
     * 重置静音标志
     */
    private void resetMuteFlag() {
        if (soundAlarm.isMuteFlag()) {
            soundAlarm.setMuteFlag(false);
        }
    }

    /**
     * 检测当前状态是否正常
     *
     * @param value
     * @return
     */
    private boolean checkStateIfNormal(String value) {
        boolean flag = false;
        if (Constant.AMQS_STATE_CONNECTED.equals(value)) {
            flag = true;
        } else if (Constant.MQ_STATE_OK.equals(value)) {
            flag = true;
        } else if (Constant.MQ_STATE_RUNNING.equals(value)) {
            flag = true;
        } else if (Constant.GW_STATE_CONNECTED.equals(value)) {
            flag = true;
        } else if (Constant.BGS_STATE_ONLINE.equals(value)) {
            flag = true;
        }
        return flag;
    }

    /**
     * 将状态转换成相应的提示语
     *
     * @param logInfo
     * @return
     */
    private LogEntity transferStateToTip(LogInfo logInfo) {
        LogEntity logEntity = new LogEntity("", "", "", "");
        logEntity.setLevel(logInfo.getLevel());
        logEntity.setLog(logInfo.getName() + ": " + logInfo.getLog());
        logEntity.setCreateTime(Time.getCurDateStr(Time.yyyy_MM_dd_HH_mm_ss));
        return logEntity;
    }

    /**
     * 检测并报警
     */
    private void checkIfAlarmAndShowErrorMsgForSysState(LogInfo info) {
        // 系统状态告警
        if (regularXMLConfiguration.getAmqs().equals(Constant.START_ALARM_YES) && info.getName().contains(Constant.XML_ELEMENT_AMQS_NAME)
                || regularXMLConfiguration.getGw().equals(Constant.START_ALARM_YES) && info.getName().contains(Constant.XML_ELEMENT_GW_NAME)
                || regularXMLConfiguration.getMqState().equals(Constant.START_ALARM_YES) && info.getName().contains(Constant.XML_ELEMENT_MQ_NAME)) {
            resetMuteFlag();
            soundAlarm.startAudioWarn();
            appendMsgAndShowAlarmDialog(transferStateToTip(info));
        } else if (regularXMLConfiguration.getOnlineUserList() != null && regularXMLConfiguration.getOnlineUserList().size() > 0
                && ifContain(regularXMLConfiguration.getOnlineUserList(), info.getName())) {
            // 用户状态告警
            resetMuteFlag();
            soundAlarm.startAudioWarn();
            appendMsgAndShowAlarmDialog(transferStateToTip(info));
        } else {
            //日志告警
            if (regularXMLConfiguration.getContent() != null && regularXMLConfiguration.getContent().size() > 0
                    && ifContain(regularXMLConfiguration.getContent(), info.getLog())) {
                resetMuteFlag();
                soundAlarm.startAudioWarn();
                appendMsgAndShowAlarmDialog(transferStateToTip(info));
            }
        }
    }

    @FXML
    public void handleSearchButtonAction(MouseEvent event) {
        List<LogInfo> logInfoList = SystemInfoManager.getInstance().getLogCacheForSearch();
        tableLog.getItems().clear();
        cellName.setCellValueFactory(new PropertyValueFactory<>("name"));
        cellLevel.setCellValueFactory(new PropertyValueFactory<>("level"));
        cellLog.setCellValueFactory(new PropertyValueFactory<>("log"));
        cellTime.setCellValueFactory(new PropertyValueFactory<>("createTime"));
        ObservableList<LogEntity> logInfoListShow = FXCollections.observableArrayList();
        if (!Strings.isNullOrEmpty(textSearch.getText())) {
            for (LogInfo logInfo : logInfoList) {
                if (logInfo.getLog().contains(textSearch.getText())) {
                    LogEntity logEntity = new LogEntity(logInfo.getLevel(), logInfo.getName(), logInfo.getLog(), logInfo.getDateTime());
                    logInfoListShow.add(logEntity);
                }
            }
        } else {
            for (LogInfo logInfo : logInfoList) {
                LogEntity logEntity = new LogEntity(logInfo.getLevel(), logInfo.getName(), logInfo.getLog(), logInfo.getDateTime());
                logInfoListShow.add(logEntity);
            }
        }
        if (logInfoListShow.size() > 0) {
            tableLog.setItems(logInfoListShow);
        }
    }

    @FXML
    public void handleAddButtonAction(MouseEvent event) {
        String content = textLog.getText();
        if (!Strings.isNullOrEmpty(content)) {
            listLog.getItems().add(content);
        }
    }

    @FXML
    public void handleDeleteLogAction(ActionEvent actionEvent) {
        int index = listLog.getSelectionModel().getSelectedIndex();
        if (index >= 0) {
            listLog.getItems().remove(index);
        }
    }

    @FXML
    public void handleSyncAction(ActionEvent actionEvent) {
        Alert _alert = new Alert(Alert.AlertType.INFORMATION,"",new ButtonType("取消", ButtonBar.ButtonData.NO),
                new ButtonType("确定", ButtonBar.ButtonData.YES));
        _alert.setHeaderText("是否同步用户");
        Optional<ButtonType> _buttonType = _alert.showAndWait();
        if(_buttonType.get().getButtonData().equals(ButtonBar.ButtonData.YES)){
            sysncUser();
        }
    }

    @FXML
    public void handleSaveConfigAction(ActionEvent actionEvent) {
        // AMQS 状态设置
        if (chkAMQS.isSelected()) {
            regularConfigManager.setAmqsState(Constant.START_ALARM_YES);
        } else {
            regularConfigManager.setAmqsState(Constant.START_ALARM_NO);
        }

        //MQ 状态设置
        if (chkMQ.isSelected()) {
            regularConfigManager.setMqState(Constant.START_ALARM_YES);
        } else {
            regularConfigManager.setMqState(Constant.START_ALARM_NO);
        }

        //GW 状态设置
        if (chkGW.isSelected()) {
            regularConfigManager.setGwState(Constant.START_ALARM_YES);
        } else {
            regularConfigManager.setGwState(Constant.START_ALARM_NO);
        }

        //用户 自动同步设置
        if (chkAuto.isSelected()) {
            regularConfigManager.setAutoSysnc(Constant.START_ALARM_YES);
        } else {
            regularConfigManager.setAutoSysnc(Constant.START_ALARM_NO);
        }

        if (listSaveState.getItems().size() >= 0) {
            List<String> onUsers = Lists.newArrayList();
            for (int i = 0; i < listSaveState.getItems().size(); i++) {
                onUsers.add(listSaveState.getItems().get(i).toString());
            }
            regularXMLConfiguration.setOnlineUserList(onUsers);
        }


        if (listState.getItems().size() >= 0) {
            List<String> offUsers = Lists.newArrayList();
            for (int i = 0; i < listState.getItems().size(); i++) {
                offUsers.add(listState.getItems().get(i).toString());
            }
            regularXMLConfiguration.setOfflineuserList(offUsers);
        }

        regularConfigManager.getLog().clear();
        if (listLog.getItems().size() > 0) {
            for (int i = 0; i < listLog.getItems().size(); i++) {
                regularConfigManager.setLogContent(listLog.getItems().get(i).toString());
            }
        }

        boolean flag = RegularXMLConfiguration.getInstance().saveConfigToXMLFile(regularConfigManager);
        if (flag) {
            regularXMLConfiguration.load();
            SystemInfoManager.getInstance().clearAllCache();
            initUser();
            Alert alert = new Alert(Alert.AlertType.NONE, "配置保存成功！", ButtonType.OK);
            alert.show();
        } else {
            Alert alert = new Alert(Alert.AlertType.NONE, "配置保存失败！", ButtonType.OK);
            alert.show();
        }
    }

    @FXML
    public void handleCancelAction(ActionEvent actionEvent) {
        stage.close();
    }

    public void init() {
        requestService.setRequestMessageListener(this);
        requestService.start();
        initUser();
        if (Constant.START_ALARM_YES.equals(regularXMLConfiguration.getAmqs())) {
            this.chkAMQS.setSelected(true);
        }
        if (Constant.START_ALARM_YES.equals(regularXMLConfiguration.getMqState())) {
            this.chkMQ.setSelected(true);
        }
        if (Constant.START_ALARM_YES.equals(regularXMLConfiguration.getGw())) {
            this.chkGW.setSelected(true);
        }
        if (Constant.START_ALARM_YES.equals(regularXMLConfiguration.getAutoSync())) {
            this.chkAuto.setSelected(true);
        }
        listState.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        listSaveState.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

        if (regularXMLConfiguration.getOnlineUserList() != null && regularXMLConfiguration.getOnlineUserList().size() > 0) {
            ObservableList<String> strList = FXCollections.observableArrayList(regularXMLConfiguration.getOnlineUserList());
            listSaveState.setItems(strList);
        }

        if (regularXMLConfiguration.getOfflineuserList() != null && regularXMLConfiguration.getOfflineuserList().size() > 0) {
            ObservableList<String> strList = FXCollections.observableArrayList(regularXMLConfiguration.getOfflineuserList());
            listState.setItems(strList);
        }


        if (regularXMLConfiguration.getContent() != null && regularXMLConfiguration.getContent().size() > 0) {
            ObservableList<String> strList = FXCollections.observableArrayList(regularXMLConfiguration.getContent());
            listLog.setItems(strList);
        }
    }

    /**
     * 同步用户
     */
    public void sysncUser() {
        try {
            List<String> userList = requestService.getUsers();
            if (userList != null && userList.size() > 0) {
                boolean flag = regularXMLConfiguration.syncUser(userList);
                if (!flag) {
                    if(syncError_alert == null){
                        syncError_alert = new Alert(Alert.AlertType.NONE, "用户同步失败！", ButtonType.OK);
                    }
                    syncError_alert.show();
                } else {
                    regularXMLConfiguration.load();
                    initUserList();
                }
            }
        } catch (Exception e) {
            if(syncError_alert == null){
                syncError_alert = new Alert(Alert.AlertType.NONE, "用户同步失败！", ButtonType.OK);
            }
            syncError_alert.show();
        }
    }

    private class CheckIp implements Runnable {

        @Override
        public void run() {
            try {
                InetAddress address = InetAddress.getByName(new URL(alarmFactory.getUserUri()).getHost());
                if (!address.isReachable(2000)) {
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            if (checkError_alert == null) {
                                checkError_alert = new Alert(Alert.AlertType.NONE, "GMS 连接异常，请检查网络！", ButtonType.OK);

                            } else {
                                if (!checkError_alert.isShowing()) {
                                    checkError_alert.show();
                                }
                            }
                        }
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void initUserList() {
        if (regularXMLConfiguration.getOnlineUserList() != null && regularXMLConfiguration.getOnlineUserList().size() > 0) {
            ObservableList<String> onlineList = FXCollections.observableArrayList(regularXMLConfiguration.getOnlineUserList());
            listSaveState.setItems(onlineList);
        } else {
            listSaveState.setItems(FXCollections.observableArrayList());
        }
        if (regularXMLConfiguration.getOfflineuserList() != null && regularXMLConfiguration.getOfflineuserList().size() > 0) {
            ObservableList<String> offlineList = FXCollections.observableArrayList(regularXMLConfiguration.getOfflineuserList());
            listState.setItems(offlineList);
        } else {
            listState.setItems(FXCollections.observableArrayList());
        }

    }

    public void addBGSOfState(ActionEvent actionEvent) {
        move(listState.getSelectionModel().getSelectedItems(), listState, listSaveState);
    }

    public void deleteBGSOfState(ActionEvent actionEvent) {
        move(listSaveState.getSelectionModel().getSelectedItems(), listSaveState, listState);
    }


    public void showAlarmDialog() {
        try {
            alarmView.start();
        } catch (Exception e) {
            Log.error("open alarm dialog fail!", e);
        }
    }

    public void showSysAlarmDialog() {
        try {
            sysAlarmView.start();
        } catch (Exception e) {
            Log.error("open sysAlarm dialog fail!", e);
        }
    }

    public void initUser() {
        if (Constant.START_ALARM_YES.equals(regularXMLConfiguration.getAutoSync())) {
            if (thread == null) {
                thread = new Thread((new Runnable() {
                    @Override
                    public void run() {
                        sysnStartFlag = true;
                        while (sysnStartFlag) {
                            Platform.runLater(new Runnable() {
                                @Override
                                public void run() {
                                    sysncUser();
                                }
                            });
                            try {
                                Thread.sleep(alarmFactory.getIntervalTime());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }));
                thread.start();
            }
        } else {
            sysnStartFlag = false;
            thread = null;
        }
        // 检测GMS地址连通性
        if (checkIpService == null || checkIpService.isShutdown()) {
            checkIpService = Executors.newSingleThreadScheduledExecutor();
            checkIpService.scheduleAtFixedRate(new CheckIp(), 0, 10000, TimeUnit.MILLISECONDS);
        }
    }

    /**
     * 释放连接
     */
    public void dispose() {
        if (thread != null) {
            sysnStartFlag = false;
            thread = null;
        }
        if (checkIpService != null) {
            checkIpService.shutdown();
        }
    }

    /**
     * 列表见移动
     *
     * @param items
     * @param from
     * @param to
     */
    private void move(ObservableList items, ListView from, ListView to) {
        List<String> list = Lists.newArrayList();
        for (int i = 0; i < items.size(); i++) {
            list.add(items.get(i).toString());
        }

        if (to.getItems().size() > 0) {
            for (int i = 0; i < to.getItems().size(); i++) {
                list.add(to.getItems().get(i).toString());
            }
        }

        if (items.size() > 0) {
            from.getItems().removeAll(items);
        }

        Collections.sort(list);
        to.getItems().clear();
        to.setItems(FXCollections.observableArrayList(list));
    }
}
